package com.frontop.terminal.gangedsocket.core;

import cn.hutool.core.thread.ThreadUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.frontop.terminal.entity.Message;
import com.frontop.terminal.gangedsocket.service.ICommandSerivce;
import com.frontop.terminal.util.ReadDataUtil;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.ConnectException;
import java.net.Socket;
import java.util.Objects;

/**
 * <p>
 * 播放联动Socket客户端
 * </p>
 *
 * @author :CCC
 * @since :2021-10-14
 **/
public class PlayGangedClient implements Runnable {

    /**
     * 停止线程标志
     */
    private static boolean release;
    private static Socket clientSocekt;
    private static DataInputStream inputStream;
    private static DataOutputStream outputStream;

    public PlayGangedClient() {
        release = true;
    }

    public static void start() {
        PlayGangedClient playGangedClient = new PlayGangedClient();
        ThreadUtil.sleep(5000);
        ThreadUtil.execAsync(playGangedClient);
    }

    public static void release() {
        System.out.println("[播放联动socket客户端]主动关闭连接并释放资源");
        release = false;
        try {
            if (Objects.nonNull(clientSocekt) && !clientSocekt.isClosed()) {
                outputStream.writeUTF(PlayGangedServiceSocket.COLSE);
                outputStream.flush();

                clientSocekt.close();
                inputStream.close();
                outputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void colse() {
        System.out.println("[播放联动socket客户端]与服务端断开连接");
        try {
            PlayGangedClient.clientSocekt.close();
            PlayGangedClient.inputStream.close();
            PlayGangedClient.outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        //获取主屏socket地址
        String host;
        String hostIp;
        String hostPort;

        //处理配置问题
        while (true) {
            try {
                host = Objects.requireNonNull(ReadDataUtil.getTerminalConfig()).getMainFrameSocketAddress();

                if (StringUtils.isBlank(host)) {
                    System.out.println("[播放联动socket客户端]启动失败,原因是主屏Socket地址为空");
                } else {
                    hostIp = host.substring(0, host.lastIndexOf(":"));
                    hostPort = host.substring(host.lastIndexOf(":") + 1);
                    break;
                }
            } catch (Exception e) {
                e.printStackTrace();
                System.err.println("[播放联动socket客户端]启动失败,原因是主屏Socket地址填写格式有误");
            }

            ThreadUtil.sleep(5000);
        }

        while (release) {
            try {
                System.out.println("[播放联动socket客户端]服务端IP:" + hostIp + "端口:" + hostPort);
                clientSocekt = new Socket(hostIp, Integer.parseInt(hostPort));
                clientSocekt.setSoTimeout(5000);
                clientSocekt.setKeepAlive(true);
                inputStream = new DataInputStream(clientSocekt.getInputStream());
                outputStream = new DataOutputStream(clientSocekt.getOutputStream());
                DelayOffset.PLAY_GANGED_CLIENT = this;

                //连接未断开的话处理信息数据
                while (!clientSocekt.isClosed()) {
                    if (inputStream.available() > 0) {
                        String msg = inputStream.readUTF();
                        System.out.println("[播放联动socket客户端]收到信息:" + msg);

                        //接收到关闭命令
                        if (msg.equals(PlayGangedServiceSocket.COLSE)) {
                            //释放
                            colse();
                        } else if (Heartbeat.HEARTBEAT_MSG.equals(msg)) {
                            //心跳
                            send(Heartbeat.HEARTBEAT_RESPONSE);
                        } else {
                            Message message = JSON.parseObject(msg, Message.class);

                            //下发的延迟包
                            if (message.getType().equals(DelayOffset.DELAY)) {
                                long millis = System.currentTimeMillis();
                                System.out.println("[播放联动-延迟补偿]本机当前milli ：" + millis);
                                int data = (int) (millis - Long.parseLong(message.getCommand()));
                                DelayOffset.addDelayRecord(data);
                            } else if (message.getType().equals(DelayOffset.TIMELINE)) {
                                //主屏时间轴
                                DelayOffset.MAIN_SCREEN_TIMELINE = Integer.parseInt(message.getCommand());
                            } else {
                                //获取消息处理器
                                ICommandSerivce iCommandSerivce = GangedMessageDisposeFactory.getWorkers(message.getType());

                                if (Objects.isNull(iCommandSerivce)) {
                                    System.out.println("[播放联动socket客户端]找不到对应处理器");
                                    continue;
                                }
                                iCommandSerivce.executeWork(message);
                            }
                        }
                    }
                }


            } catch (EOFException e) {
                System.out.println("[播放联动socket客户端]数据读取到了末尾");
            } catch (ConnectException e) {
                System.out.println("[播放联动socket客户端]服务端离线");
                ThreadUtil.sleep(5000);
            } catch (IOException e) {
                System.out.println("[播放联动socket客户端]Stream closed.");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    public void send(String msg) {
        if (!clientSocekt.isClosed()) {
            try {
                System.out.println("[播放联动socket客户端]收到发送命令,即将发送内容:" + msg);
                outputStream.writeUTF(msg);
                outputStream.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            System.out.println("[播放联动socket客户端]无法发送信息,连接已经关闭");
        }
    }
}
